import { MATERIAL_PREVIEW_DEFAULT_PROPS } from '@app-base/common/utils/materialPreview';
import { ctx2 } from '@app-base/module';
import { MessageTip } from '@app-cad/common/utils/MessageTip';
import { Button, Form, Modal, Skeleton, Tabs, Tree } from 'antd';
import { omit } from 'lodash';
import React, { useEffect, useMemo, useState } from 'react';
import {
  getNodeTypeMark,
  isFieldsChanged,
  MaterialNodeType,
} from '../MaterialTree/utils';
import { getMaterialConfig, materialKeyMap } from '../common/MetalIconMapping';
import MaterialAppearancePanel from './MaterialAppearancePanel';
import MaterialPropertyForm from './MaterialPropertyForm';
import materialTreeData from './constants';
import { materialHttpApi } from '@app-base/server/material-http';

interface AppearanceFieldsProps {
  appearanceKey: string;
  baseColor: string;
  isUseStandardMaterialAppearance: boolean;
}
interface MaterialDetailPanelProps {
  selectNode?: CmdMaterialSpace.TreeNode;
  onClose: () => void;
  setTreeUpdateKey: () => void;
  activeTab: string;
  setActiveTab: (tab: string) => void;
}

const APPEARANCE_INITIAL: AppearanceFieldsProps = {
  appearanceKey: 'custom-powercad-styles',
  baseColor: MATERIAL_PREVIEW_DEFAULT_PROPS.baseColor,
  isUseStandardMaterialAppearance: true,
};
const MaterialDetailPanel: React.FC<MaterialDetailPanelProps> = ({
  selectNode,
  onClose,
  setTreeUpdateKey,
  activeTab,
  setActiveTab,
}) => {
  const [loading, setLoading] = useState(false);
  const [remoteDetail, setRemoteDetail] =
    useState<CmdMaterialSpace.MaterialDetail>();

  const [propertyFormValues, setPropertyFormValues] =
    useState<CmdMaterialSpace.MaterialPropertyFormValues>();

  const [appearanceFields, setAppearanceFields] =
    useState<AppearanceFieldsProps>(APPEARANCE_INITIAL);

  const { appearanceKey, baseColor, isUseStandardMaterialAppearance } =
    appearanceFields;

  const [formSettings] = Form.useForm();

  // 初始属性表单值，用于对比是否有差异
  const [propertyFormInitialValues, setPropertyFormInitialValues] =
    useState<Partial<CmdMaterialSpace.MaterialPropertyFormValues>>();
  useEffect(() => {
    if (
      selectNode &&
      [
        MaterialNodeType.CustomMat,
        MaterialNodeType.FavMaterial,
        MaterialNodeType.StandardMaterial,
      ].includes(selectNode.typeMark as MaterialNodeType)
    ) {
      QueryMaterialDetail(selectNode);
    }
  }, [selectNode]);

  const isStandardMaterial = useMemo(() => {
    if (selectNode?.typeMark === 'standard-material') return true;
    if (
      selectNode?.typeMark === 'fav-material' &&
      Object.prototype.hasOwnProperty.call(
        omit(materialKeyMap, ['custom-material']),
        selectNode.iconKey,
      )
    )
      return true;
    return false;
  }, [selectNode]);

  const QueryMaterialDetail = async (selectNode: CmdMaterialSpace.TreeNode) => {
    setLoading(true);
    try {
      const res = await materialHttpApi.getMaterialDetail({
        source: getNodeTypeMark(selectNode),
        id: selectNode.id,
      });
      const _detail = (res.data ?? {}) as CmdMaterialSpace.MaterialDetail;
      setRemoteDetail(_detail);

      setAppearanceFields(
        _detail.nextMaterialAppearanceResultVO
          ? {
              baseColor: _detail.nextMaterialAppearanceResultVO?.baseColor,
              appearanceKey:
                _detail.nextMaterialAppearanceResultVO?.appearanceKey,
              isUseStandardMaterialAppearance:
                _detail.nextMaterialAppearanceResultVO
                  ?.isUseStandardMaterialAppearance == '0'
                  ? false
                  : true,
            }
          : APPEARANCE_INITIAL,
      );

      const initialFormValues = {
        massDensity: 1000,
        modeType: '线性弹性各向同性',
        ..._detail?.nextMaterialAttrResultVO,
        name: _detail?.name,
        materialKind: selectNode.parentName,
      };
      // 设置初始属性表单值
      setPropertyFormInitialValues(initialFormValues);
      setPropertyFormValues(initialFormValues);
    } catch (error) {
      console.error('获取材料详情失败:', error);
    } finally {
      setLoading(false);
    }
  };

  // 属性表单字段对比
  const isPropertyChanged = useMemo(() => {
    if (!propertyFormInitialValues || !propertyFormValues) return false;
    return isFieldsChanged(
      [
        'modeType',
        'youngsModulus',
        'poissonsRatios',
        'massDensity',
        'thermalExpansionCoefficient',
        'yieldStrength',
        'name',
        'materialKind',
      ],
      propertyFormInitialValues,
      propertyFormValues,
    );
  }, [propertyFormInitialValues, propertyFormValues]);

  function normalizeBoolean(value: boolean | '0' | '1'): boolean {
    if (value === '1' || value === true) return true;
    if (value === '0' || value === false) return false;
    return !!value;
  }
  // 外观字段对比
  const isAppearanceChanged = useMemo(() => {
    if (!remoteDetail) return false;
    const remoteAppearance = {
      ...APPEARANCE_INITIAL,
      ...remoteDetail.nextMaterialAppearanceResultVO,
    };
    const rewrite = {
      ...remoteAppearance,
      isUseStandardMaterialAppearance: normalizeBoolean(
        remoteAppearance.isUseStandardMaterialAppearance,
      ),
    };
    return isFieldsChanged(
      ['baseColor', 'appearanceKey', 'isUseStandardMaterialAppearance'],
      appearanceFields,
      rewrite,
    );
  }, [remoteDetail, appearanceFields]);

  const isSaveDisabled = !isPropertyChanged && !isAppearanceChanged;

  // 保存函数
  const handleSave = async () => {
    const v = await formSettings.validateFields().catch(() => false);
    if (v) {
      const detail: CmdMaterialSpace.MaterialUpdateDetail = {
        id: remoteDetail.materialId,
        name: propertyFormValues.name,
        nextMaterialAttrUpdateVO: {
          ...propertyFormValues,
          id: remoteDetail.nextMaterialAttrResultVO?.id,
        },
        nextMaterialAppearanceUpdateVO: {
          ...remoteDetail.nextMaterialAppearanceResultVO,
          baseColor,
          appearanceKey,
          isUseStandardMaterialAppearance: isUseStandardMaterialAppearance
            ? '1'
            : '0',
        },
      };
      try {
        await materialHttpApi.saveMaterialDetail(detail);
        MessageTip.success('保存成功');
        QueryMaterialDetail(selectNode);
        setTreeUpdateKey();
      } catch (e) {
        MessageTip.error('保存失败');
      }
    }
  };
  // 当前材料的预览属性
  const MaterialPreviewParams = useMemo(() => {
    const defaultProps = { ...MATERIAL_PREVIEW_DEFAULT_PROPS };

    const renderProps = getMaterialConfig(appearanceKey).renderProps;

    const o = renderProps ? { ...defaultProps, ...renderProps } : defaultProps;

    return { ...o, baseColor };
  }, [appearanceKey, baseColor]);

  useEffect(() => {
    if (isUseStandardMaterialAppearance) {
      const renderProps = getMaterialConfig(appearanceKey).renderProps;
      setAppearanceFields((o) => ({ ...o, baseColor: renderProps.baseColor }));
    }
  }, [isUseStandardMaterialAppearance, appearanceKey]);

  const applyMaterial = async () => {
    try {
      await ctx2.coreEngine.execCmd({
        c: 'SaveAppData',
        key: 'physicalMaterial',
        data: JSON.stringify(MaterialPreviewParams),
      });
      ctx2.viewer.sceneSetup.setUpGlobalPBRMaterial();
      MessageTip.success('应用材料成功');
    } catch {
      MessageTip.error('应用材料失败');
    }
  };

  const onCloseBeforeSave = async () => {
    if (!isSaveDisabled) {
      Modal.confirm({
        title: '是否保存当前内容',
        okText: '保存',
        cancelText: '不保存',
        onOk: async () => {
          const v = await formSettings.validateFields().catch(() => false);
          if (v) {
            await handleSave();
            onClose();
          }
        },
        onCancel: () => onClose(),
      });
    } else {
      onClose();
    }
  };

  if (
    ![
      MaterialNodeType.CustomMat,
      MaterialNodeType.StandardMaterial,
      MaterialNodeType.FavMaterial,
    ].includes(selectNode?.typeMark as MaterialNodeType)
  ) {
    return (
      <div className='flex-1 relative'>
        <div className='h-[565px] flex items-center  justify-center text-gray-400'>
          选择材料以应用/编辑
        </div>
        <Button
          type='primary'
          className='absolute bottom-0 right-2'
          onClick={onClose}
        >
          关闭
        </Button>
      </div>
    );
  }

  return (
    <div className='flex flex-col flex-1 px-2 h-[570px]'>
      {loading ? (
        <Skeleton
          active
          paragraph={{ rows: 12 }}
          className='h-full'
        />
      ) : (
        <>
          <Tabs
            activeKey={activeTab}
            onChange={setActiveTab}
            className='mb-0 flex-shrink-0'
            tabBarStyle={{ marginBottom: 0 }}
            items={[
              {
                label: '属性',
                key: 'property',
                children: (
                  <div className='h-[506px] overflow-auto p-2'>
                    <MaterialPropertyForm
                      remoteDetail={remoteDetail}
                      materialKind={selectNode.parentName}
                      disabled={isStandardMaterial}
                      formSettings={formSettings}
                      onValuesChange={setPropertyFormValues}
                      propertyFormInitialValues={propertyFormInitialValues}
                    />
                  </div>
                ),
              },
              {
                label: '外观',
                key: 'appearance',
                children: (
                  <div style={{ display: 'flex', height: 506 }}>
                    {/* 左侧树结构，添加滚动条 */}
                    <div
                      style={{
                        width: 260,
                        borderRight: '1px solid #eee',
                        padding: 8,
                        height: '100%',
                        overflow: 'auto',
                      }}
                    >
                      <Tree
                        treeData={materialTreeData}
                        selectedKeys={[appearanceKey || '']}
                        defaultExpandAll
                        showLine
                        showIcon
                        onSelect={([key]) => {
                          if (key) {
                            setAppearanceFields((o) => ({
                              ...o,
                              appearanceKey: key.toString(),
                            }));
                          }
                        }}
                        fieldNames={{
                          title: 'label',
                          key: 'key',
                          children: 'children',
                        }}
                        disabled={isStandardMaterial}
                      />
                    </div>
                    {/* 右侧外观面板 */}
                    <div style={{ flex: 1, paddingLeft: 16 }}>
                      <MaterialAppearancePanel
                        onColorChange={(c) =>
                          setAppearanceFields((o) => ({ ...o, baseColor: c }))
                        }
                        disabled={isStandardMaterial}
                        MaterialPreviewParams={MaterialPreviewParams}
                        isUseStandardMaterialAppearance={
                          isUseStandardMaterialAppearance
                        }
                        setIsUseStandardMaterialAppearance={(i) =>
                          setAppearanceFields((o) => ({
                            ...o,
                            isUseStandardMaterialAppearance: i,
                          }))
                        }
                      />
                    </div>
                  </div>
                ),
              },
            ]}
          />
          <div className='flex justify-end gap-3 mr-2 mt-2 flex-shrink-0'>
            <Button onClick={onCloseBeforeSave}>关闭</Button>
            <Button
              onClick={handleSave}
              disabled={isSaveDisabled}
              type='primary'
            >
              保存
            </Button>

            <Button
              type='primary'
              disabled={!selectNode}
              onClick={applyMaterial}
            >
              应用材料
            </Button>
          </div>
        </>
      )}
    </div>
  );
};

export default MaterialDetailPanel;
